package com.fram.service.admin.impl;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.fram.bean.admin.ordermain.request.OrderDeliveredRequest;
import com.fram.bean.admin.ordermain.request.OrderRequest;
import com.fram.bean.admin.ordermain.response.OrderResponse;
import com.fram.bean.admin.ordermain.response.OrderSearchResponse;
import com.fram.bean.admin.ordermain.response.PageAdminReportForm;
import com.fram.bean.sys.PageBean;
import com.fram.common.canstant.ErrCode;
import com.fram.common.canstant.PublicConstant;
import com.fram.common.enums.OrderStatusEnum;
import com.fram.common.enums.PayCodeEnum;
import com.fram.common.exception.ProAffairException;
import com.fram.common.exception.ProException;
import com.fram.common.exception.ProRunTimeException;
import com.fram.common.exception.ProValiDataException;
import com.fram.common.util.alipay.AlipayUtils;
import com.fram.common.util.base.BaseService;
import com.fram.common.util.date.DateUtils;
import com.fram.common.util.json.JSONTools;
import com.fram.common.util.wxpay.WXPayUtils;
import com.fram.entity.OrderMain;
import com.fram.entity.OrderRefund;
import com.fram.entity.SysPayment;
import com.fram.entity.UserTransactionFlow;
import com.fram.mapper.OrderMainMapper;
import com.fram.mapper.OrderRefundMapper;
import com.fram.mapper.SysPaymentMapper;
import com.fram.mapper.UserTransactionFlowMapper;
import com.fram.service.admin.OrderService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

@Service
public class OrderServiceImpl extends BaseService implements OrderService {

	private static Logger LOG = LoggerFactory.getLogger(OrderServiceImpl.class);

	@Autowired
	private OrderMainMapper orderMainMapper;
	@Autowired
	private OrderRefundMapper orderRefundMapper;
	@Autowired
	private SysPaymentMapper sysPaymentMapper;
	@Autowired
	private UserTransactionFlowMapper userTransactionFlowMapper;

	/**
	 * 根据ID查询订单详情
	 */
	@Override
	public OrderResponse adminOrderDetail(Long id) throws ProException {
		OrderResponse i = orderMainMapper.adminOrderDetail(id);
		if (i == null) {
			throw new ProValiDataException(ErrCode.NO_DATA.getReturnCode(), ErrCode.NO_DATA.getReturnMsg());
		}
		i.setOrderStatusValue(OrderStatusEnum.orderStatusVaule(i.getOrderStatus()));
		if (i.getRefundOrder() != null) {
			i.setRefundStatusValue(OrderStatusEnum.orderStatusVaule(i.getRefundOrder().getRefundStatus()));
		}
		return i;
	}

	/**
	 * 订单改为已发货
	 */
	@Override
	public void orderDelivered(OrderDeliveredRequest request) throws ProException {
		if (!StringUtils.isEmpty(request.getRemark()) && request.getRemark().length() > 256) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "备注字数不能超过256个字");
		}
		OrderMain order = orderMainMapper.selectByPrimaryKey(request.getId());
		if (order == null) {
			throw new ProValiDataException(ErrCode.NO_DATA.getReturnCode(), ErrCode.NO_DATA.getReturnMsg());
		}
		if (request.getDistributorId() != null && request.getDistributorId() != order.getDistributorId()) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "该订单无权操作");
		}
		if (OrderStatusEnum.MAIN_ORDER_STATUS_2.getStatus() != order.getOrderStatus()) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "该订单不是已支付，不能发货");
		}
		OrderMain update = new OrderMain();
		update.setId(request.getId());
		update.setOrderStatus(OrderStatusEnum.MAIN_ORDER_STATUS_3.getStatus());
		update.setDeliveryTime(new Date());
		update.setRemark(request.getRemark());
		int i = orderMainMapper.updateByPrimaryKeySelective(update);
		if (i <= 0) {
			throw new ProValiDataException(ErrCode.FAIL.getReturnCode(), "发货失败");
		}
	}

	/**
	 * 
	 * 订单全部查询
	 */
	@Override
	public PageInfo<OrderSearchResponse> selectOrder(PageBean<OrderRequest> request) throws ProException {
		PageHelper.startPage(request.getPageNum(), request.getPageSize());
		if (!StringUtils.isEmpty(request.getParam().getCreateStartTime())) {
			request.getParam().setCreateStartTime(request.getParam().getCreateStartTime() + " 00:00:00");
		}
		if (!StringUtils.isEmpty(request.getParam().getCreateEndTime())) {
			try {
				request.getParam().setCreateEndTime(DateUtils.DF_SEPARATE.get()
						.format(DateUtils.getAddorSubtractTimes(DateUtils.DF_SEPARATE_YMD.get().parse(request.getParam().getCreateEndTime()), 0, 0, 0, 1, 0, 0)));
			} catch (ParseException e) {
			}
		}
		List<OrderSearchResponse> list = orderMainMapper.selectOrderForAdmin(request.getParam());
		if (list == null || list.size() == 0) {
			throw new ProValiDataException(ErrCode.NO_DATA.getReturnCode(), ErrCode.NO_DATA.getReturnMsg());
		}
		for (OrderSearchResponse r : list) {
			r.setOrderStatusValue(OrderStatusEnum.orderStatusVaule(r.getOrderStatus()));
			r.setRefundStatusValue(OrderStatusEnum.orderStatusVaule(r.getRefundStatus()));
		}
		return new PageInfo<>(list);
	}

	@Override
	@Transactional
	public void updateApplyFailRefund(OrderRefund refund) throws ProAffairException {
		OrderRefund old = orderRefundMapper.selectByPrimaryKey(refund.getId());
		if (old == null) {
			throw new ProRunTimeException(ErrCode.NO_DATA.getReturnCode(), ErrCode.NO_DATA.getReturnMsg());
		}
		if (OrderStatusEnum.REFUND_ORDER_STATUS_7.getStatus() != old.getRefundStatus()) {
			throw new ProRunTimeException(ErrCode.ORDER_STATUS_UPDATE.getReturnCode(), ErrCode.ORDER_STATUS_UPDATE.getReturnMsg());
		}
		refund.setRefundStatus(OrderStatusEnum.REFUND_ORDER_STATUS_10.getStatus());
		refund.setUpdateTime(null);
		if (orderRefundMapper.updateByPrimaryKeySelective(refund) <= 0) {
			throw new ProRunTimeException(ErrCode.FAIL.getReturnCode(), "修改退款订单失败");
		}
	}

	@Override
	@Transactional
	public String updateApplySuccessRefund(OrderRefund refund, Long distributorId) throws ProAffairException {
		OrderRefund old = orderRefundMapper.selectByPrimaryKey(refund.getId());
		if (old == null) {
			throw new ProRunTimeException(ErrCode.NO_DATA.getReturnCode(), ErrCode.NO_DATA.getReturnMsg());
		}
		old.setUpdateTime(null);
		old.setFailRemark("");
		if (OrderStatusEnum.REFUND_ORDER_STATUS_7.getStatus() != old.getRefundStatus()) {
			throw new ProRunTimeException(ErrCode.ORDER_STATUS_UPDATE.getReturnCode(), ErrCode.ORDER_STATUS_UPDATE.getReturnMsg());
		}
		OrderResponse orderDetail = null;
		try {
			orderDetail = adminOrderDetail(old.getMainOrderId());
		} catch (ProException e) {
			throw new ProRunTimeException(e.getErrorCode(), e.getErrorMsg());
		}
		// 如果是已支付 则直接退款
		if (OrderStatusEnum.MAIN_ORDER_STATUS_2.getStatus() == orderDetail.getOrderStatus()) {
			return refundPrice(orderDetail, old);
		}
		// 如果是已发货，已收货 改为收取快递中
		if (OrderStatusEnum.MAIN_ORDER_STATUS_3.getStatus() == orderDetail.getOrderStatus() || OrderStatusEnum.MAIN_ORDER_STATUS_4.getStatus() == orderDetail.getOrderStatus()) {
			old.setRefundStatus(OrderStatusEnum.REFUND_ORDER_STATUS_8.getStatus());
			if (orderRefundMapper.updateByPrimaryKeySelective(old) <= 0) {
				throw new ProRunTimeException(ErrCode.FAIL.getReturnCode(), "修改退货信息失败");
			}
			return "退回货物过后退款到支付账户";
		}
		return null;
	}

	@Override
	@Transactional
	public void refundUserPrice(OrderRefund refund, Long distributorId) throws ProAffairException {
		OrderRefund old = orderRefundMapper.selectByPrimaryKey(refund.getId());
		if (old == null) {
			throw new ProRunTimeException(ErrCode.NO_DATA.getReturnCode(), ErrCode.NO_DATA.getReturnMsg());
		}
		old.setUpdateTime(null);
		old.setFailRemark("");
		if (OrderStatusEnum.REFUND_ORDER_STATUS_8.getStatus() != old.getRefundStatus()) {
			throw new ProRunTimeException(ErrCode.ORDER_STATUS_UPDATE.getReturnCode(), ErrCode.ORDER_STATUS_UPDATE.getReturnMsg());
		}
		OrderResponse orderDetail = null;
		try {
			orderDetail = adminOrderDetail(old.getMainOrderId());
		} catch (ProException e) {
			throw new ProRunTimeException(e.getErrorCode(), e.getErrorMsg());
		}
		// 如果是已发货，已收货 改为收取快递中
		if (OrderStatusEnum.MAIN_ORDER_STATUS_3.getStatus() == orderDetail.getOrderStatus() || OrderStatusEnum.MAIN_ORDER_STATUS_4.getStatus() == orderDetail.getOrderStatus()) {
			refundPrice(orderDetail, old);
		}
	}

	// 调用第三方退款接口退款
	private String refundPrice(OrderResponse orderDetail, OrderRefund old) throws ProAffairException {
		SysPayment payment = sysPaymentMapper.selectByPayTypeAndSource(orderDetail.getPayType(), orderDetail.getSource());
		if (payment == null) {
			throw new ProRunTimeException(ErrCode.NO_DATA.getReturnCode(), "获取支付信息失败");
		}
		if (payment.getPayType() == PayCodeEnum.WECHAT.getType()) {
			Map<String, String> refundMap = WXPayUtils.wechatRefund(orderDetail, orderDetail.getRefundOrder(), payment);
			old.setRefundBillNumber(refundMap.get("transaction_id"));
			LOG.error("-后台->订单退款-微信->{}", JSONTools.obj2json(refundMap));
		} else if (payment.getPayType() == PayCodeEnum.ALIPAY.getType()) {
			old.setRefundBillNumber(AlipayUtils.refund(payment, orderDetail.getPayNumber(), orderDetail.getRefundOrder().getRefundPrice()));
		} else {
			throw new ProRunTimeException(ErrCode.FAIL.getReturnCode(), "无匹配的支付信息");
		}
		old.setRefundTime(new Date());
		old.setRefundStatus(OrderStatusEnum.REFUND_ORDER_STATUS_9.getStatus());
		if (orderRefundMapper.updateByPrimaryKeySelective(old) <= 0) {
			throw new ProRunTimeException(ErrCode.FAIL.getReturnCode(), "修改退货信息失败");
		}
		// 记录流水
		UserTransactionFlow flow = new UserTransactionFlow();
		flow.setUserId(orderDetail.getUserId());
		flow.setResType(PublicConstant.RES_TYPE_6);
		flow.setResId(orderDetail.getId());
		flow.setFlowType(PublicConstant.FLOW_TYPE_1);
		flow.setPrice(old.getRefundPrice());
		flow.setReason("商品退款");
		if (userTransactionFlowMapper.insertSelective(flow) <= 0) {
			throw new ProRunTimeException(ErrCode.FAIL.getReturnCode(), "记录流水失败");
		}
		return "已经退款到用户支付账户";
	}

	@Override
	@Transactional
	public PageAdminReportForm reportForm(Long distributorId) throws ProAffairException {
		String key = "ADMIN_PAGE_REPORT_FORM_" + distributorId;
		int db = 15;
		Object data = redisService.get(db, key);
		if (!StringUtils.isEmpty(data)) {
			return JSONTools.jsonStr2obj(data.toString(), PageAdminReportForm.class);
		}
		PageAdminReportForm form = new PageAdminReportForm();
		Date date = new Date();
		// 今日
		String today = DateUtils.DF_SEPARATE_YMD.get().format(date);
		form.setTodayData(orderMainMapper.orderStatusByDay(today + " 00:00:00", today + " 23:59:59", distributorId));
		// 昨日
		String yesterDay = DateUtils.DF_SEPARATE_YMD.get().format(DateUtils.getAddorSubtractTimes(date, 0, 0, 0, -1, 0, 0));
		form.setYesterdayData(orderMainMapper.orderStatusByDay(yesterDay + " 00:00:00", yesterDay + " 23:59:59", distributorId));
		// 七天之内
		String seven = DateUtils.DF_SEPARATE_YMD.get().format(DateUtils.getAddorSubtractTimes(date, 0, 0, 0, -6, 0, 0));
		form.setSevenDayData(orderMainMapper.orderStatusByDay(seven + " 00:00:00", today + " 23:59:59", distributorId));
		// 这周
		String thisWeek = DateUtils.DF_SEPARATE_YMD.get().format(DateUtils.getAddorSubtractTimes(date, 0, 0, 0, (DateUtils.getWeekByDay(date) - 1) * -1, 0, 0));
		form.setThisWeekData(orderMainMapper.orderStatusByDay(thisWeek + " 00:00:00", today + " 23:59:59", distributorId));
		// 30天
		String thirty = DateUtils.DF_SEPARATE_YMD.get().format(DateUtils.getAddorSubtractTimes(date, 0, 0, 0, -29, 0, 0));
		form.setThirtyDayData(orderMainMapper.orderStatusByDay(thirty + " 00:00:00", today + " 23:59:59", distributorId));
		// 这个月
		String thisMonth = today.substring(0, 8) + "01";
		form.setThisMonthData(orderMainMapper.orderStatusByDay(thisMonth + " 00:00:00", today + " 23:59:59", distributorId));

		// 存入redis 整点30分更新一次
		int expireTime = 0;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		int minute = calendar.get(Calendar.MINUTE);
		if (minute > 30) {
			expireTime = 60 - minute;
		} else {
			expireTime = 30 - minute;
		}
		redisService.set(db, key, JSONTools.obj2json(form), expireTime * 60);
		return form;
	}

}
